#include "uio.h"
#include <map>
std::map<WORD, WORD>wellFitColor = {
    {0x00,0x02},
    {0x10,0x0e},
    {0x20,0x01},
    {0x30,0x04},
    {0x40,0x0e},
    {0x50,0x06},
    {0x60,0x04},
    {0x70,0x00},
    {0x80,0x06},
    {0x90,0x0e},
    {0xA0,0x05},
    {0xB0,0x04},
    {0xC0,0x0e},
    {0xD0,0x06},
    {0xE0,0x04},
    {0xF0,0x00}
};
std::ostream& operator<<(std::ostream& Ostr, COORD Val)
{
    Ostr << "X:" << Val.X << " Y:" << Val.Y;
    return Ostr;
}
std::ostream& operator<<(std::ostream& Ostr, SMALL_RECT Val)
{
    Ostr << "t" << Val.Top << " b" << Val.Bottom << " l" << Val.Left << " r" << Val.Right;
    return Ostr;
}

PEN::PEN()
{
    this->hOut = nullptr;
    this->wAttr = 0x00;
}

PEN::PEN(HANDLE OutputHandle)
{
    this->hOut = OutputHandle;
    if (this->hOut == nullptr)
    {
        cout << "Fail to get standard output handle." << endl;
        exit(-1);
    }
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    if (!GetConsoleScreenBufferInfo(this->hOut, &csbi))
    {
        cout << "Fail to get console screen buffer info." << endl;
        exit(-1);
    }
    this->wAttr = csbi.wAttributes;
    if (csbi.dwCursorPosition.X)cout << endl;
}

void PEN::NewLine()
{
    COORD CurPos;
    this->GetCursorPos(CurPos);
    CurPos.X = 0;
    CurPos.Y = CurPos.Y + 1;
    this->SetCursorPos(CurPos);
}

BOOL PEN::GetCursorPos(COORD&lp)
{
    CONSOLE_SCREEN_BUFFER_INFO csbi;
    if (GetConsoleScreenBufferInfo(this->hOut, &csbi))
    {
        lp = csbi.dwCursorPosition;
        return true;
    }
    return false;
}
BOOL PEN::SetCursorPos(COORD p)
{
    return SetConsoleCursorPosition(this->hOut, p);
}


BOOL PEN::Write(const char* str)
{
    DWORD n = 0;
    return WriteConsoleA(this->hOut, str, strlen(str), &n, NULL);
}

BOOL PEN::Write(char ch)
{
    DWORD n = 0;
    return WriteConsoleA(this->hOut, &ch, 1, &n, NULL);
}

BOOL PEN::Write(WORD wAttr, const char* str)
{
    WORD b_wAttr = this->wAttr;
    this->SetColor(wAttr);
    this->Write(str);
    this->SetColor(b_wAttr);
    return 0;
}

BOOL PEN::Write(WORD wAttr, char ch)
{
    WORD b_wAttr = this->wAttr;
    this->SetColor(wAttr);
    this->Write(ch);
    this->SetColor(b_wAttr);
    return 0;
}

BOOL PEN::Write(COORD coord, const char* str)
{
    COORD back;
    this->GetCursorPos(back);
    this->SetCursorPos(coord);
    this->Write(str);
    this->SetCursorPos(back);
    return 0;
}

BOOL PEN::Write(COORD coord, char ch)
{
    COORD back;
    this->GetCursorPos(back);
    this->SetCursorPos(coord);
    this->Write(ch);
    this->SetCursorPos(back);
    return 0;
}

BOOL PEN::Write(WORD wAttr, COORD coord, const char* str)
{
    WORD b_wAttr = this->wAttr;
    this->SetColor(wAttr);
    this->Write(coord, str);
    this->SetColor(b_wAttr);
    return 0;
}

BOOL PEN::Write(WORD wAttr, COORD coord, char ch)
{
    WORD b_wAttr = this->wAttr;
    this->SetColor(wAttr);
    this->Write(coord, ch);
    this->SetColor(b_wAttr);
    return 0;
}
BOOL PEN::SetColor(WORD wAttr)
{
    if (SetConsoleTextAttribute(this->hOut, wAttr))
    {
        this->wAttr = wAttr;
        return true;
    }
    return false;
}

BOOL PEN::GetColor(WORD wAttr)
{
    return wAttr;
}
